﻿using System;
using System.Text;
using GeoAPI.Geometries;

namespace NetTopologySuite.Geometries
{
	public static class CoordinateSequences
	{
		public static void Reverse(ICoordinateSequence seq)
		{
			int num = seq.Count - 1;
			int num2 = num / 2;
			for (int i = 0; i <= num2; i++)
			{
				CoordinateSequences.Swap(seq, i, num - i);
			}
		}

		public static void Swap(ICoordinateSequence seq, int i, int j)
		{
			if (i == j)
			{
				return;
			}
			for (int k = 0; k < seq.Dimension; k++)
			{
				double ordinate = seq.GetOrdinate(i, (Ordinate)k);
				seq.SetOrdinate(i, (Ordinate)k, seq.GetOrdinate(j, (Ordinate)k));
				seq.SetOrdinate(j, (Ordinate)k, ordinate);
			}
		}

		public static void Copy(ICoordinateSequence src, int srcPos, ICoordinateSequence dest, int destPos, int length)
		{
			for (int i = 0; i < length; i++)
			{
				CoordinateSequences.CopyCoord(src, srcPos + i, dest, destPos + i);
			}
		}

		public static void CopyCoord(ICoordinateSequence src, int srcPos, ICoordinateSequence dest, int destPos)
		{
			int num = System.Math.Min(src.Dimension, dest.Dimension);
			for (int i = 0; i < num; i++)
			{
				Ordinate ordinate = (Ordinate)i;
				double ordinate2 = src.GetOrdinate(srcPos, ordinate);
				dest.SetOrdinate(destPos, ordinate, ordinate2);
			}
		}

		public static bool IsRing(ICoordinateSequence seq)
		{
			int count = seq.Count;
			return count == 0 || (count > 3 && seq.GetOrdinate(0, Ordinate.X) == seq.GetOrdinate(count - 1, Ordinate.X) && seq.GetOrdinate(0, Ordinate.Y) == seq.GetOrdinate(count - 1, Ordinate.Y));
		}

		public static ICoordinateSequence EnsureValidRing(ICoordinateSequenceFactory fact, ICoordinateSequence seq)
		{
			int count = seq.Count;
			if (count == 0)
			{
				return seq;
			}
			if (count <= 3)
			{
				return CoordinateSequences.CreateClosedRing(fact, seq, 4);
			}
			if (seq.GetOrdinate(0, Ordinate.X) == seq.GetOrdinate(count - 1, Ordinate.X) && seq.GetOrdinate(0, Ordinate.Y) == seq.GetOrdinate(count - 1, Ordinate.Y))
			{
				return seq;
			}
			return CoordinateSequences.CreateClosedRing(fact, seq, count + 1);
		}

		private static ICoordinateSequence CreateClosedRing(ICoordinateSequenceFactory fact, ICoordinateSequence seq, int size)
		{
			ICoordinateSequence coordinateSequence = fact.Create(size, seq.Dimension);
			int count = seq.Count;
			CoordinateSequences.Copy(seq, 0, coordinateSequence, 0, count);
			for (int i = count; i < size; i++)
			{
				CoordinateSequences.Copy(seq, 0, coordinateSequence, i, 1);
			}
			return coordinateSequence;
		}

		public static ICoordinateSequence Extend(ICoordinateSequenceFactory fact, ICoordinateSequence seq, int size)
		{
			ICoordinateSequence coordinateSequence = fact.Create(size, seq.Ordinates);
			int count = seq.Count;
			CoordinateSequences.Copy(seq, 0, coordinateSequence, 0, count);
			if (count > 0)
			{
				for (int i = count; i < size; i++)
				{
					CoordinateSequences.Copy(seq, count - 1, coordinateSequence, i, 1);
				}
			}
			return coordinateSequence;
		}

		public static bool IsEqual(ICoordinateSequence cs1, ICoordinateSequence cs2)
		{
			int count = cs1.Count;
			int count2 = cs2.Count;
			if (count != count2)
			{
				return false;
			}
			int num = System.Math.Min(cs1.Dimension, cs2.Dimension);
			for (int i = 0; i < count; i++)
			{
				for (int j = 0; j < num; j++)
				{
					Ordinate ordinate = (Ordinate)j;
					double ordinate2 = cs1.GetOrdinate(i, ordinate);
					double ordinate3 = cs2.GetOrdinate(i, ordinate);
					if (cs1.GetOrdinate(i, ordinate) != cs2.GetOrdinate(i, ordinate) && (!double.IsNaN(ordinate2) || !double.IsNaN(ordinate3)))
					{
						return false;
					}
				}
			}
			return true;
		}

		public static string ToString(ICoordinateSequence cs)
		{
			int count = cs.Count;
			if (count == 0)
			{
				return "()";
			}
			int dimension = cs.Dimension;
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append('(');
			for (int i = 0; i < count; i++)
			{
				if (i > 0)
				{
					stringBuilder.Append(" ");
				}
				for (int j = 0; j < dimension; j++)
				{
					if (j > 0)
					{
						stringBuilder.Append(",");
					}
					double ordinate = cs.GetOrdinate(i, (Ordinate)j);
					stringBuilder.Append(string.Format("{0:0.#}", ordinate));
				}
			}
			stringBuilder.Append(')');
			return stringBuilder.ToString();
		}
	}
}
